package net.lazyandroid.namewars.utils ;
public class MD5
{
	private String b64pad = new String("");
    private int chrsz = 8 ;
    
    public MD5(String b64pad, int chrsz )
    {
    
       this.b64pad = b64pad;
       if (chrsz == 8 || chrsz == 16)
       {
           this.chrsz = chrsz;
       } 
    }
    
    public MD5()
    {
    	
    }
    
    public String hash(String s)
    {
        return (this.hex_MD5(s));
    } 
    
    private String hex_MD5(String s)
    {
        return (this.binl2hex(this.core_MD5(this.str2binl(s), s.length() * chrsz)));
    } 
    
    public String b64_MD5(String s)
    {
        return (this.binl2b64(this.core_MD5(this.str2binl(s), s.length() * chrsz)));
    } 
    
    public String str_MD5(String s)
    {
        return (this.binl2str(this.core_MD5(this.str2binl(s), s.length() * chrsz)));
    } 
    private int MD5_cmn(int q, int a, int b, int x, int s, int t)
    {
        return (this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b));
    } // End of the function
    private int MD5_ff(int a, int b, int c, int d, int x, int s, int t)
    {
        return (this.MD5_cmn(b & c | (b ^ (int)4.294967E+009) & d, a, b, x, s, t));
    } // End of the function
    private int MD5_gg(int a, int b, int c, int d, int x, int s, int t)
    {
        return (this.MD5_cmn(b & d | c & (d ^ (int)4.294967E+009), a, b, x, s, t));
    } // End of the function
    private int MD5_hh(int a, int b, int c, int d, int x, int s, int t)
    {
        return (this.MD5_cmn(b ^ c ^ d, a, b, x, s, t));
    } // End of the function
    private int MD5_ii(int a, int b, int c, int d, int x, int s, int t)
    {
        return (this.MD5_cmn(c ^ (b | d ^ (int)4.294967E+009), a, b, x, s, t));
    } // End of the function
    private int[] core_MD5(int[] x, int len)
    {
    	x[len >> 5] = x[len >> 5] | 128 << len % 32;
        if((len + 64 >>> 9 << 4) + 14 < x.length)
        	x[(len + 64 >>> 9 << 4) + 14] = len;
        int _loc2 = 1732584193;
        int _loc3 = -271733879;
        int _loc4 = -1732584194;
        int _loc5 = 271733878;
        for (int _loc6 = 0; _loc6 < x.length - 16; _loc6 = _loc6 + 16)
        {
            int _loc11 = _loc2;
            int _loc10 = _loc3;
            int _loc8 = _loc4;
            int _loc9 = _loc5;
            _loc2 = this.MD5_ff(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 0], 7, -680876936);
            _loc5 = this.MD5_ff(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 1], 12, -389564586);
            _loc4 = this.MD5_ff(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 2], 17, 606105819);
            _loc3 = this.MD5_ff(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 3], 22, -1044525330);
            _loc2 = this.MD5_ff(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 4], 7, -176418897);
            _loc5 = this.MD5_ff(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 5], 12, 1200080426);
            _loc4 = this.MD5_ff(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 6], 17, -1473231341);
            _loc3 = this.MD5_ff(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 7], 22, -45705983);
            _loc2 = this.MD5_ff(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 8], 7, 1770035416);
            _loc5 = this.MD5_ff(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 9], 12, -1958414417);
            _loc4 = this.MD5_ff(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 10], 17, -42063);
            _loc3 = this.MD5_ff(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 11], 22, -1990404162);
            _loc2 = this.MD5_ff(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 12], 7, 1804603682);
            _loc5 = this.MD5_ff(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 13], 12, -40341101);
            _loc4 = this.MD5_ff(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 14], 17, -1502002290);
            _loc3 = this.MD5_ff(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 15], 22, 1236535329);
            _loc2 = this.MD5_gg(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 1], 5, -165796510);
            _loc5 = this.MD5_gg(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 6], 9, -1069501632);
            _loc4 = this.MD5_gg(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 11], 14, 643717713);
            _loc3 = this.MD5_gg(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 0], 20, -373897302);
            _loc2 = this.MD5_gg(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 5], 5, -701558691);
            _loc5 = this.MD5_gg(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 10], 9, 38016083);
            _loc4 = this.MD5_gg(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 15], 14, -660478335);
            _loc3 = this.MD5_gg(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 4], 20, -405537848);
            _loc2 = this.MD5_gg(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 9], 5, 568446438);
            _loc5 = this.MD5_gg(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 14], 9, -1019803690);
            _loc4 = this.MD5_gg(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 3], 14, -187363961);
            _loc3 = this.MD5_gg(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 8], 20, 1163531501);
            _loc2 = this.MD5_gg(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 13], 5, -1444681467);
            _loc5 = this.MD5_gg(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 2], 9, -51403784);
            _loc4 = this.MD5_gg(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 7], 14, 1735328473);
            _loc3 = this.MD5_gg(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 12], 20, -1926607734);
            _loc2 = this.MD5_hh(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 5], 4, -378558);
            _loc5 = this.MD5_hh(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 8], 11, -2022574463);
            _loc4 = this.MD5_hh(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 11], 16, 1839030562);
            _loc3 = this.MD5_hh(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 14], 23, -35309556);
            _loc2 = this.MD5_hh(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 1], 4, -1530992060);
            _loc5 = this.MD5_hh(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 4], 11, 1272893353);
            _loc4 = this.MD5_hh(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 7], 16, -155497632);
            _loc3 = this.MD5_hh(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 10], 23, -1094730640);
            _loc2 = this.MD5_hh(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 13], 4, 681279174);
            _loc5 = this.MD5_hh(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 0], 11, -358537222);
            _loc4 = this.MD5_hh(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 3], 16, -722521979);
            _loc3 = this.MD5_hh(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 6], 23, 76029189);
            _loc2 = this.MD5_hh(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 9], 4, -640364487);
            _loc5 = this.MD5_hh(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 12], 11, -421815835);
            _loc4 = this.MD5_hh(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 15], 16, 530742520);
            _loc3 = this.MD5_hh(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 2], 23, -995338651);
            _loc2 = this.MD5_ii(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 0], 6, -198630844);
            _loc5 = this.MD5_ii(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 7], 10, 1126891415);
            _loc4 = this.MD5_ii(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 14], 15, -1416354905);
            _loc3 = this.MD5_ii(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 5], 21, -57434055);
            _loc2 = this.MD5_ii(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 12], 6, 1700485571);
            _loc5 = this.MD5_ii(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 3], 10, -1894986606);
            _loc4 = this.MD5_ii(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 10], 15, -1051523);
            _loc3 = this.MD5_ii(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 1], 21, -2054922799);
            _loc2 = this.MD5_ii(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 8], 6, 1873313359);
            _loc5 = this.MD5_ii(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 15], 10, -30611744);
            _loc4 = this.MD5_ii(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 6], 15, -1560198380);
            _loc3 = this.MD5_ii(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 13], 21, 1309151649);
            _loc2 = this.MD5_ii(_loc2, _loc3, _loc4, _loc5, x[_loc6 + 4], 6, -145523070);
            _loc5 = this.MD5_ii(_loc5, _loc2, _loc3, _loc4, x[_loc6 + 11], 10, -1120210379);
            _loc4 = this.MD5_ii(_loc4, _loc5, _loc2, _loc3, x[_loc6 + 2], 15, 718787259);
            _loc3 = this.MD5_ii(_loc3, _loc4, _loc5, _loc2, x[_loc6 + 9], 21, -343485551);
            _loc2 = this.safe_add(_loc2, _loc11);
            _loc3 = this.safe_add(_loc3, _loc10);
            _loc4 = this.safe_add(_loc4, _loc8);
            _loc5 = this.safe_add(_loc5, _loc9);
        } 
        //core_MD5 : ,1561135756,-1496068863,1124957801,698242743
        
        int[] results = new int[]{_loc2, _loc3, _loc4, _loc5};
        Log.d("core_MD5 : "+ results);
        return results ;
    } // End of the function
  
    private int safe_add(int x, int y)
    {
        int a = (x & 65535) + (y & 65535);
        int b = ((x >> 16) + (y >> 16) + (a >> 16));
        return (b << 16 | a & 65535);
    } // End of the function
    private int bit_rol(int num, int cnt)
    {
        return (num << cnt | num >>> 32 - cnt);
    } 
    private int[] str2binl(String str)
    {
    	int theLen = str.length() * chrsz ;
    	int[] binl = new int[theLen];
        int _chrsz = (1 << chrsz) - 1;
        for (int i = 0; i < theLen; i = i + chrsz)
        {
        	binl[i >> 5] = binl[i >> 5] | (str.codePointAt(i / chrsz) & _chrsz) << i % 32;
        } 
        //str2binl : ,1701340520
        return (binl);
    } 
    private String binl2str(int[] bin)
    {
        String str = new String("");
        int _chrsz = (1 << chrsz) - 1;
        for (int i = 0; i < bin.length * 32; i = i + chrsz)
        {
        	str = str +(Character.toChars((bin[i >> 5] >>> i % 32 & _chrsz))).toString();
        } // end of for
        return (str);
    } 

    private String binl2hex(int[] binarray)
    {
    	//8c0a0d5d01cdd3a6697e0d43b7569e29
        String vars = "0123456789abcdef";
        String hexStr = new String("");
        for (int i = 0; i < binarray.length * 4; ++i)
        {
        	char pre = vars.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 15) ;
        	char next = vars.charAt(binarray[i >> 2] >> i % 4 * 8 & 15) ;
        	hexStr = hexStr + pre + next;
        } // end of for
        
        Log.d("binl2hex :" + hexStr);
        return (hexStr);
    } 
    
    private String binl2b64(int[] binarray)
    {
        String vars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        String b64Str = new String("");
        for (int i = 0; i < binarray.length * 4; i = i + 3)
        {
            int idx = (binarray[i >> 2] >> 8 * (i % 4) & 255) << 16 | (binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4) & 255) << 8 | binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4) & 255;
            for (int j = 0; j < 4; ++j)
            {
                if (i * 8 + j * 6 > binarray.length * 32)
                {
                	b64Str = b64Str + b64pad;
                    continue;
                } // end if
                b64Str = b64Str + vars.charAt(idx >> 6 * (3 - j) & 63);
            } // end of for
        } // end of for
        return (b64Str);
    }

    public int[] md5array(String s)
    {
       int[] md5_arr = this.core_MD5(this.str2binl(s), s.length() * chrsz);
        int[] array = new int[4 * 32];
        for (int i = 0; i < 4; ++i)
        {
            for (int j = 0; j < 32; ++j)
            {
            	array[i*32 + j] = (md5_arr[i] >> j & 1);
            } // end of for
        } 
        return (array);
    } 
    
} 

